% !TeX program = xelatex 
\documentclass[xcolor=svgnames,10pt,UTF8]{ctexbeamer}
%\documentclass[aspectratio=169,xcolor=svgnames,10pt]{beamer}

\RequirePackage{slide}

%\logo{\includegraphics[scale=0.015]{../figure/logo.jpg}}
\title{SystemVerilog芯片验证}
\subtitle{第6章~随机化}
%\author{王旭}
%\institute{深圳信息职业技术学院~微电子学院}
\date{\today}

\begin{document}

\frame{\titlepage}
%\LogoOn
%\LogoOff

\section{带有随机属性的类} \label{Simple Class with Random Variables}

\subsection{随机属性} \label{Random Variables and Class}

\begin{frame}[t,fragile]{随机属性}

	\begin{enumerate}
		\item 标准随机属性（rand）：它的每次随机化都是独立的，其随机值在取值范围内均匀分布。
		\item 循环随机属性（randc）：它在随机化时会将取值范围内的数值逐个随机取出，随机化的取值范围会越来越小。当全部数值被取出后再次重复前面的操作。
	\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-10},consecutivenumbers=false]
{src/ch6/sec1/1/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-15},consecutivenumbers=false]
{src/ch6/sec1/1/test.sv}

\begin{lstlisting}
: a=9, b=12
: a=11, b=0
: a=10, b=6
...
\end{lstlisting}

\end{frame}

\subsection{约束块} \label{Constraint block}

\begin{frame}[t,fragile]{约束块}

约束表达式描述了单个随机属性的取值范围，也可以描述随机属性之间的依赖关系。

每个约束表达式只能使用一个关系运算符，

约束表达式间如果存在约束冲突会导致随机化失败。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]
{src/ch6/sec1/2/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\begin{lstlisting}
: a=2, b=15
: a=5, b=8
: a=8, b=12
...
\end{lstlisting}

\end{frame}

\subsection{随机化方法} \label{Checking Values Using Constraints}

\begin{frame}[t,fragile]{随机化方法}

randomize是类的内置方法，它按照约束要求执行对象的随机化，randomize方法可以随机化二值和四值的整型随机属性，但是只能生成二值的随机值。它有如下3种使用方法。

\begin{enumerate}
	\item \lstinline[language=SystemVerilog]|randomize()|：不带参数时，对象的所有随机属性都将被随机化。
	\item \lstinline[language=SystemVerilog]|randomize(arg)|：只随机化参数列表中的随机属性，类的所有约束仍然有效。
	\item \lstinline[language=SystemVerilog]|randomize(null)|：参数为null，只检查随机属性的取值是否满足约束。如果随机属性的取值违反约束，则返回错误值0。
\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-17},consecutivenumbers=false]
{src/ch6/sec1/3/test.sv}

\begin{lstlisting}
: a=2, b=15
: a=13, b=15
"../test.sv", 15: test.unnamed$$_0.unnamed$$_3: started at 0ps failed at 0ps
	Offending 'tr.randomize(1)'
\end{lstlisting}

注意randomize方法不能在构造方法中使用，因为构造方法需要完成随机化前的准备工作，例如打开或关闭约束、改变权重分布或添加新约束。

\end{frame}

\subsection{约束开关} \label{subsec constraint mode}

\begin{frame}[t,fragile]{约束开关}

类的内置方法constraint\_mode可以打开或关闭约束块，它的使用方法如下。

\begin{enumerate}
	\item 句柄.约束块.constraint\_mode(arg)：当参数arg为0时关闭约束块，为1时开启约束块。
	\item 句柄.约束块.constraint\_mode()：查询某个约束块是否打开。
	\item 句柄.constraint\_mode(arg)：打开或关闭对象中的所有约束块。
\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-25},consecutivenumbers=false]
{src/ch6/sec1/4/test.sv}

\begin{lstlisting}
: a=5, b=15
: a=14, b=8
: a=6, b=12
...
: a=9, b=5
: a=10, b=14
: a=2, b=11
...
tr.constraint_mode=0
\end{lstlisting}

\end{frame}

\subsection{随机开关} \label{subsec rand mode}

\begin{frame}[t,fragile]{随机开关}

类的内置方法rand\_mode可以设置随机属性的激活状态，它的使用方式有三种。

\begin{enumerate}
	\item 句柄.随机属性.rand\_mode(arg)：设置某个随机属性的激活状态。当参数arg为0时随机属性处于非激活状态，不参与随机化，为1时处于激活状态，参与随机化。
	\item 句柄.随机属性.rand\_mode()：查询某个随机属性的激活状态。
	\item 句柄.rand\_mode(arg)：设置所有随机属性的激活状态。
\end{enumerate}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-26},consecutivenumbers=false]
{src/ch6/sec1/5/test.sv}

\begin{lstlisting}
Error-[CNST-CIF] Constraints inconsistency failure
../test.sv, 13
  Constraints are inconsistent and cannot be solved.
  Please check the inconsistent constraints being printed above and rewrite 
  them.

"../test.sv", 13: test.unnamed$$_0.unnamed$$_1: started at 0ps failed at 0ps
	Offending 'tr.randomize()'
: a=0, b=0
: a=0, b=10
: a=0, b=11
...
\end{lstlisting}

\end{frame}

\subsection{伪随机发生器种子} \label{PRNG Seed}

\begin{frame}[t,fragile]{伪随机发生器种子}

约束求解器负责求解约束块中的约束表达式，并生成满足约束的随机值。伪随机发生器（Pseudo Random Number Generator, PRNG）在启动时会使用一个初始种子（seed）产生所有的随机值。

\begin{enumerate}
	\item VCS：simv +ntb\_random\_seed=n或simv +ntb\_random\_seed\_automatic。
	\item Xcelium：xrun -svseed n或random。
	\item Questasim：vsim -sv\_seed n或random。
\end{enumerate}

\end{frame}

\section{随机属性的约束} \label{Constraint Details}

\subsection{分布约束} \label{Distribution}

\begin{frame}[t,fragile]{分布约束}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-18},consecutivenumbers=false]
{src/ch6/sec2/1/transaction.svh}

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{随机属性a和b取值的概率分布} \label{table: dist of random variables}
	\begin{tabular}{lllll}
		\hline
		\rowcolor{black!10}随机属性 & 取0概率   & 取1概率   & 取2概率   & 取3概率   \\\hline
		a                       & 40/220 & 60/220 & 60/220 & 60/220 \\\hline
		b                       & 40/100 & 20/100 & 20/100 & 20/100 \\\hline
	\end{tabular}
\end{table}

\end{frame}

\subsection{取值集合} \label{Set Membership and the Inside Operator}

\begin{frame}[t,fragile]{取值集合}

inside操作符用于创建随机属性的整数取值集合。如果没有其他约束，求解器会按相同的概率在集合中取值，集合上下限可以使用变量。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-17},consecutivenumbers=false]
{src/ch6/sec2/2/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-17},consecutivenumbers=false]
{src/ch6/sec2/2/test.sv}

\end{frame}

\begin{frame}[t,fragile]{数组可以作为inside的集合成员}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-17},consecutivenumbers=false]
{src/ch6/sec2/3/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

测试模块在运行时可以根据需要修改动态数组array的内容，从而改变随机属性a的取值范围。注意，不要频繁地修改inside操作符中的取值集合，因为大量的约束求解会严重降低测试平台的运行性能。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-15},consecutivenumbers=false]
{src/ch6/sec2/3/test.sv}

\end{frame}

\begin{frame}[t,fragile]{将类中数组的元素值不重复的逐个取出}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-17},consecutivenumbers=false]
{src/ch6/sec2/4/transaction.svh}

\end{frame}

\subsection{唯一性约束} \label{Uniqueness constraints}

\begin{frame}[t,fragile]{唯一性约束unique}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]
{src/ch6/sec2/5/transaction.svh}

\end{frame}

\subsection{条件约束} \label{Conditional relations}

\begin{frame}[t,fragile]{条件约束}

条件约束可以让约束表达式在满足一定的条件时才会生效。

条件约束使用逻辑蕴含（logic implication）操作符“->”或if else语句声明。

逻辑蕴含表达式A->B与逻辑表达式(!A||B)等价。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{逻辑蕴含表达式A->B的真值表} \label{Implication operator truth table}%
	\begin{tabular}{lll}
		\hline
		\rowcolor{black!10}A->B & B=0 & B=1 \\
		\hline
		A=0                     & 1   & 1   \\
		A=1                     & 0   & 1   \\\hline
	\end{tabular}%
\end{table}%

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]
{src/ch6/sec2/6/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-16},consecutivenumbers=false]
{src/ch6/sec2/6/test.sv}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch6/sec2/7/transaction.svh}

\end{frame}

\subsection{等价操作符} \label{Equivalence Operator}

\begin{frame}[t,fragile]{等价操作符}

等价（equivalence）操作符“<->”是双向约束的，等价表达式A<->B与逻辑表达式(A->B)\&\&(B->A)等价。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{等价表达式A<->B的真值表} \label{Equivalence operator truth table}%
	\begin{tabular}{lll}
		\hline
		\rowcolor{black!10}A<->B & B=0 & B=1 \\ \hline
		A=0                      & 1   & 0   \\
		A=1                      & 0   & 1   \\ \hline
	\end{tabular}%
\end{table}%

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch6/sec2/8/transaction.svh}

\end{frame}

\subsection{行内约束} \label{subsec inline constraint}

\begin{frame}[t,fragile]{行内约束}

	with语句可以在调用randomize方法时添加额外的行内约束。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-16},consecutivenumbers=false]
{src/ch6/sec2/9/test.sv}

\end{frame}

\subsection{软约束} \label{subsec soft constraint}

\begin{frame}[t,fragile]{软约束}
	
类中默认的约束是硬约束，在随机化时如果不能满足硬约束则仿真器会报错。但是为了方便代码的复用，可以在类中定义软（soft）约束。所有软约束的优先级都低于硬约束。在随机化时如果软约束与其他硬约束有冲突，仿真器不会报错。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]
{src/ch6/sec2/10/transaction.svh}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-16},consecutivenumbers=false]
{src/ch6/sec2/10/test.sv}

\end{frame}

\section{随机数组的约束} \label{Iterative and Array Constraints}

\subsection{数组长度的约束} \label{Array Size}

\begin{frame}[t,fragile]{使用size方法可以约束数组或队列的长度}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch6/sec3/1/transaction.svh}

\end{frame}

\subsection{数组元素和的约束} \label{Sum of Elements}

\begin{frame}[t,fragile]{使用sum方法可以约束数组元素的和}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]
{src/ch6/sec3/2/transaction.svh}

\end{frame}

\subsection{数组元素的约束} \label{Constraining Individual Array and Queue Elements}

\begin{frame}[t,fragile]{数组元素的约束}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-22},consecutivenumbers=false]
{src/ch6/sec3/3/transaction.svh}

\end{frame}

\subsection{没有重复值的随机数组} \label{Generating an Array of Unique Values}

\begin{frame}[t,fragile]{使用unique操作符可以生成没有重复值的随机数组}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-18},consecutivenumbers=false]
{src/ch6/sec3/4/transaction.svh}

\end{frame}

\section{约束随机属性求解顺序} \label{Solution Probabilities}

\begin{frame}[t,fragile]{约束随机属性求解顺序}

没有约束时随机属性的取值应该在取值范围内均匀分布，这样随机化才能更好地覆盖整个设计空间。当添加约束后，随机属性取值的概率分布往往受约束影响而发生改变。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]
{src/ch6/sec4/1/transaction.svh}

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{未指定求解顺序时随机值的概率分布} \label{Solutions for Imp1 class}%
	\begin{tabular}{lll}
		\hline
		\rowcolor{black!10} a & b & 概率  \\ \hline
		0                     & 0 & 1/5 \\
		1                     & 0 & 1/5 \\
		1                     & 1 & 1/5 \\
		1                     & 2 & 1/5 \\
		1                     & 3 & 1/5 \\ \hline
	\end{tabular}%
\end{table}%

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-23},consecutivenumbers=false]
{src/ch6/sec4/1/test.sv}

\begin{lstlisting}
'{1984, 1990, 1985, 1968, 2073}
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{使用关键字solve可以改变随机属性的求解顺序}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]
{src/ch6/sec4/2/transaction.svh}

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{指定solve a before b后随机值的概率分布} \label{Solutions for solve s before d constraint}%
	\begin{tabular}{lll}
		\hline
		\rowcolor{black!10} a & b & 概率  \\ \hline
		0                     & 0 & 1/2 \\
		1                     & 0 & 1/8 \\
		1                     & 1 & 1/8 \\
		1                     & 2 & 1/8 \\
		1                     & 3 & 1/8 \\ \hline
	\end{tabular}%
\end{table}%

\end{frame}

\begin{frame}[t,fragile]{}

将求解顺序约束改成solve b before a。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{指定solve b before a后随机值的概率分布} \label{Solutions for solve d before s constraint}%
	\begin{tabular}{lll}
		\hline
		\rowcolor{black!10}a & b & 概率  \\ \hline
		0                    & 0 & 1/8 \\
		1                    & 0 & 1/8 \\
		1                    & 1 & 1/4 \\
		1                    & 2 & 1/4 \\
		1                    & 3 & 1/4 \\ \hline
	\end{tabular}%
\end{table}%

\end{frame}

\section{pre\_randomize和post\_randomize方法} \label{The pre_randomize and post_randomize Functions}

\begin{frame}[t,fragile]{pre\_randomize和post\_randomize方法}

pre\_randomize和post\_randomize是类的内置方法，它们分别在randomize方法运行的前后被自动调用，它们主要做一些随机化的准备和收尾工作。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-23},consecutivenumbers=false]
{src/ch6/sec5/1/transaction.svh}

\end{frame}

\section{随机数函数} \label{Random Number Functions}

\begin{frame}[t,fragile]{}

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{常用的随机数函数} \label{normal distribution function}%
	\begin{tabular}{ll}
		\hline
		\rowcolor{black!10}函数名                                  & 功能               \\ \hline
		\lstinline[language=SystemVerilog]|$random()|           & 均匀分布，返回32位有符号随机数 \\
		\lstinline[language=SystemVerilog]|$urandom()|          & 均匀分布，返回32位无符号随机数 \\
		\lstinline[language=SystemVerilog]|$urandom_range()|    & 在指定范围内的平均分布      \\
		\lstinline[language=SystemVerilog]|$dist_uniform()|     & 均匀分布             \\
		\lstinline[language=SystemVerilog]|$dist_normal()|      & 正态分布             \\
		\lstinline[language=SystemVerilog]|$dist_poisson()|     & 泊松分布             \\
		\lstinline[language=SystemVerilog]|$dist_exponential()| & 指数衰减分布           \\ \hline
	\end{tabular}%
\end{table}%

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
a = $urandom_range(3, 10); // 生成3到10之间的随机数
a = $urandom_range(10, 3); // 生成3到10之间的随机数
b = $urandom_range(5);     // 生成0到5之间的随机数
\end{lstlisting}

\end{frame}

\end{document}
